var nextBlockEles=[];
window.onload=()=>{
	var eles=[],data=[],pos=[],btnList=[];
	var btnNames=["start","restart","pause","left","right","round","down"],devBtn=["export","import","clear"];
	var timeoutThread,centerX,centerY,rounds=-1,blockId=-1,nextBlockId,nextRounds,score=0,running=0;
	initGame();
	createBtn();
	buttonBind();
	keyboardBind();
	function initGame(){
		const mainDiv=document.getElementById("main");
		if (mode==="dev"){
			console.log("[Welcome]","Hello, Developer!");
			document.getElementById("scoreLabel").innerText="Edit block:";
			document.getElementById("scoreValue").innerText="";
			mainDiv.innerHTML="<h1 style='margin-left: 50px;margin-top: 60px'>Dev mode</h1><h4 style='margin-left: 40px;margin-top: 10px'>you can only edit block</h4>";
			mainDiv.style.height="250px";
		}
		var i,j,line,dataLine,div,lineDiv;
		if (mode==="game") {
			for (i = 0; i < 20; i++) {
				line = [];
				dataLine = [];
				lineDiv = document.createElement("div");
				lineDiv.setAttribute("class", "line");
				for (j = 0; j < 10; j++) {
					div = document.createElement("div");
					div.setAttribute("class", "littleDiv");
					line[j] = div;
					dataLine[j] = "";
					lineDiv.appendChild(div);
				}
				eles[i] = line;
				data[i] = dataLine;
				mainDiv.appendChild(lineDiv);
			}
		}
		const nextBlock=document.getElementById("nextBlock");
		for(i=0;i<5;i++){
			line=[];
			lineDiv=document.createElement("div");
			lineDiv.setAttribute("class","line");
			for (j=0;j<5;j++){
				div=document.createElement("div");
				div.setAttribute("class","littleDiv");
				div.style.backgroundColor="#0000";
				if (mode==="dev")div.setAttribute("onclick",`nextBlockClick(${j},${i})`);
				line[j]=div;
				lineDiv.append(div);
			}
			nextBlockEles[i]=line;
			nextBlock.append(lineDiv);
		}
	}
	function createBtn(){
		const body = document.getElementsByTagName("body")[0];
		var btns;
		if (mode==="game"){
			btns=btnNames;
		}else {
			btns=devBtn;
		}
		for (const key in btns) {
			btnList[btns[key]]=document.createElement("input");
			btnList[btns[key]].setAttribute("type","button");
			btnList[btns[key]].setAttribute("value",btns[key]);
			body.append(btnList[btns[key]]);
		}
	}
	function buttonBind(){
		const bind=(name,handles)=> btnList[name].onclick=handles;
		if (mode==="dev") {
			bind("export", exportCustomBlock);
			bind("import", importCustomBlock);
			bind("clear", clearCustomBlock);
		}else {
			bind("start",()=>{pause();start();});
			bind("restart",restart);
			bind("pause",pause);
			bind("round",round);
			bind("down",down);
			bind("left",left);
			bind("right",right);
		}
	}
	function keyboardBind(){
		if (mode==="game") {
			window.onkeydown = e => {
				if (e.keyCode === 48 || e.keyCode === 96) {
					clearTimeout(timeoutThread);
					start();
				} else if (e.keyCode === 82) restart();
				else if (e.keyCode === 32 || e.keyCode === 80) pause();
				else if (e.keyCode === 38 || e.keyCode === 87) round();
				else if (e.keyCode === 40 || e.keyCode === 83) down();
				else if (e.keyCode === 37 || e.keyCode === 65) left();
				else if (e.keyCode === 39 || e.keyCode === 68) right();
			}
		}
	}
	function flushGame(){
		clearScreen();
		setBlockColor();
		if (hasBlock()){
			setBlockData();
			blockId=-1;
		}
		if (!isEmptyLine(data[0])){
			openModal("Game over!","Your score is "+score+", you can keep up the good work!<br>Thank you for playing this game!");
			return true;
		}
	}
	function start(){
		running=1;
		document.getElementById("status").style.display="none";
		if(blockId===-1){
			blockId=rounds===-1?Math.floor(Math.random() * blocks.length):nextBlockId;
			rounds=rounds===-1?Math.floor(Math.random() * 4):nextRounds;
			nextBlockId = Math.floor(Math.random() * blocks.length);
			nextRounds = Math.floor(Math.random() * 4);
			centerX = 4;
			centerY = 0;
			nextBlock();
		}
		pos=blockModel();
		clearLine();
		centerY++;
		if(flushGame())return;
		timeoutThread=setTimeout(start,runTimeout);
	}
	function restart(){
		blockId=-1;
		score=0;
		document.getElementById("scoreValue").innerText=score;
		clearTimeout(timeoutThread);
		for (let i = 0; i < 20; i++) for(let j=0; j < 10; j++) data[i][j]="";
		start();
	}
	function pause(){
		switch (running) {
			case 1:
				document.getElementById("status").style.display="inline";
				clearTimeout(timeoutThread);
				running=0;
				break;
			case 0:
				if (blockId!==-1) {
					start();
					document.getElementById("status").style.display = "none";
					running=1;
				}
		}
	}
	function round(){
		if (strict&&running===0)return;
		var newBlock=blockModel(blockId,rounds+1,centerX,centerY);
		if (!newBlock)return;
		for(var i=0;i<newBlock.length;i++){
			var x=newBlock[i][0],y=newBlock[i][1];
			if (validPos(x,y)){if (getDataByPos(x,y))return;}else return;
		}
		rounds++;
		pos=blockModel(blockId,rounds,centerX,centerY);
		flushGame();
	}
	function down(){
		if (strict&&running===0)return;
		var newBlock=blockModel(blockId,rounds,centerX,centerY+1);
		if (!newBlock)return;
		for(var i=0;i<newBlock.length;i++){
			var x=newBlock[i][0],y=newBlock[i][1];
			if (validPos(x,y)){if (getDataByPos(x,y))return;}else return;
		}
		centerY++;
		pos=blockModel(blockId,rounds,centerX,centerY);
		flushGame();
	}
	function left(){
		if (strict&&running===0)return;
		var newBlock=blockModel(blockId,rounds,centerX-1,centerY);
		if (!newBlock)return;
		for(var i=0;i<newBlock.length;i++){
			var x=newBlock[i][0],y=newBlock[i][1];
			if (validPos(x,y)){if(getDataByPos(x,y))return;}else return;
		}
		centerX--;
		pos=blockModel(blockId,rounds,centerX,centerY);
		flushGame();
	}
	function right(){
		if (strict&&running===0)return;
		var newBlock=blockModel(blockId,rounds,centerX+1,centerY);
		if (!newBlock)return;
		for(var i=0;i<newBlock.length;i++){
			var x=newBlock[i][0],y=newBlock[i][1];
			if (validPos(x,y)){if(getDataByPos(x,y))return;}else return;
		}
		centerX++;
		pos=blockModel(blockId,rounds,centerX,centerY);
		flushGame();
	}
	function nextBlock(){
		var block=blockModel(nextBlockId,nextRounds,2,2);
		const validPos=(x,y)=> x>=0&&x<5&&y>=0&&y<5;
		const setBlockColor=(x,y,color)=> getEleByPos(x,y).style.backgroundColor=color??blockColor(nextBlockId);
		const getEleByPos=(x,y)=> nextBlockEles[y][x];
		const clearScreen=()=> {for (var i = 0; i < 5; i++) for (var j = 0; j < 5; j++) setBlockColor(i, j, "#0000");}
		clearScreen();
		for (var i=0;i<block.length;i++){
			var x=block[i][0];
			var y=block[i][1];
			if (validPos(x,y))setBlockColor(x,y);else return true;
		}
	}
	const getEleByPos=(x,y)=> validPos(x,y)?eles[y][x]:undefined;
	function blockModel(id,round,x,y){
		if (blockId===-1)return;
		var count = blocks[id??blockId].length,model = blocks[id??blockId][(round??rounds)%count],block = [];
		for (let i = 0; i < model.length; i++) block[i]=[model[i][0]+(x??centerX),model[i][1]+(y??centerY)];
		return block;
	}
	const blockColor=id=> colors[id??blockId];
	const getDataByPos=(x,y)=>validPos(x,y)?data[y][x]:"";
	const setBlockData=()=>{
		for(var i=0;i<pos.length;i++){
			var x=pos[i][0],y=pos[i][1];
			if(validPos(x,y)) data[y][x]=blockColor(blockId);
		}
	};
	const setBlockColor=()=>{
		for(var i=0;i<pos.length;i++){
			var x=pos[i][0],y=pos[i][1];
			if(validPos(x,y)) getEleByPos(x,y).style.backgroundColor=blockColor(blockId);
		}
	};
	function hasBlock(){
		for(var i=0;i<pos.length;i++){
			var x=pos[i][0],y=pos[i][1];
			if(validPos(x,y)) if(getDataByPos(x,y+1)!==""||y===19) return true;
		}
		return false;
	}
	const validPos=(x,y)=>x>=0&&y>=0&&x<10&&y<20;
	const clearScreen=()=>{for(var x=0;x<10;x++) for(var y=0;y<20;y++) if(getDataByPos(x,y)==="") getEleByPos(x,y).style.backgroundColor="#99808080"; else getEleByPos(x,y).style.backgroundColor=getDataByPos(x,y);}
	const clearLine=()=>{
		for(var y=0;y<20;y++){
			if(isFullLine(data[y])){
				for(var k=0;k<10;k++)data[y][k]="";
				for(var i=0;i<19;i++) for(var j=19;j>=1;j--) if(isEmptyLine(data[j]) && !isEmptyLine(data[j-1]))for(k=0;k<10;k++){data[j][k]=data[j-1][k];data[j-1][k]="";}
			}
		}
	}
	const isEmptyLine=line=>{
		for(var i=0;i<line.length;i++)if(line[i]!=="")return false;
		return true;
	}
	const isFullLine=line=>{
		for(var i=0;i<line.length;i++)if(line[i]==="")return false;
		addScore(10*oneBlockScore);
		return true;
	}
	const addScore=value=>document.getElementById("scoreValue").innerText=(score+=value);
	const openModal=(title,message)=>{
		document.getElementsByClassName("modal-title")[0].innerHTML=title;
		document.getElementsByClassName("modal-message")[0].innerHTML=message;
		document.getElementById("modal").style.display="block";
	}
	function exportCustomBlock(){
		var str="[";
		var flag=0;
		for (var i=0;i<5;i++){
			for (var j=0;j<5;j++){
				if (nextBlockEles[j][i].style.backgroundColor!=="rgba(0, 0, 0, 0)"){
					str+="["+(i-2)+","+(j-2)+"],";
					flag=1;
				}
			}
		}
		if (flag===0){
			console.log("[]");
			return;
		}
		str=str.substr(0,str.length-1);
		str+="]";
		console.log(str);
	}
	function importCustomBlock(){
		var str=prompt("input block data:","[]");
		var block=JSON.parse(str);
		clearCustomBlock();
		for (var i=0;i<block.length;i++){
			var x=block[i][0],y=block[i][1];
			nextBlockEles[y+2][x+2].style.backgroundColor="#000f";
		}
	}
	function clearCustomBlock(){
		for (var i=0;i<5;i++){
			for (var j=0;j<5;j++){
				nextBlockEles[i][j].style.backgroundColor="#0000";
			}
		}
	}
}
const closeModal=()=> document.getElementById("modal").style.display="none";
const nextBlockClick=(x,y)=>{
	var ele=nextBlockEles[y][x];
	var color=ele.style.backgroundColor.toString();
	if (color==="rgba(0, 0, 0, 0)")color="#000f";else color="#0000";
	ele.style.backgroundColor=color;
}